/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace DaveSexton.DocProject.ExternalUI
{
	internal sealed class SortableDocProjectItemList : BindingList<DocProjectItemBase>
	{
		#region Public Properties
		protected override bool SupportsSortingCore
		{
			get
			{
				return true;
			}
		}

		protected override ListSortDirection SortDirectionCore
		{
			get
			{
				return sort;
			}
		}

		protected override PropertyDescriptor SortPropertyCore
		{
			get
			{
				return sortProperty;
			}
		}
		#endregion

		#region Private / Protected
		private ListSortDirection sort;
		private PropertyDescriptor sortProperty;
		private readonly List<DocProjectItemBase> items, defaultSortItems;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="SortableDocProjectItemList" /> class.
		/// </summary>
		public SortableDocProjectItemList(List<DocProjectItemBase> items)
			: base(items)
		{
			this.items = items;
			defaultSortItems = new List<DocProjectItemBase>(items);
		}
		#endregion

		#region Methods
		protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
		{
			if (prop != sortProperty || sort != direction)
			{
				items.Sort(delegate(DocProjectItemBase item1, DocProjectItemBase item2)
				{
					object value1 = prop.GetValue(item1);
					object value2 = prop.GetValue(item2);

					int s;

					if (value1 == null)
						s = (value2 == null) ? 0 : -1;
					else
					{
						IComparable comparable = value1 as IComparable;

						if (comparable != null)
							s = comparable.CompareTo(value2);
						else
							s = string.Compare(value1.ToString(), value2.ToString(), StringComparison.OrdinalIgnoreCase);
					}

					return (direction == ListSortDirection.Ascending) ? s : -s;
				});

				sort = direction;
				sortProperty = prop;

				OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, prop));
			}
		}

		protected override void RemoveSortCore()
		{
			if (sortProperty == null)
				return;

			items.Clear();

			items.AddRange(defaultSortItems);

			PropertyDescriptor prop = sortProperty;

			sort = ListSortDirection.Ascending;
			sortProperty = null;

			OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, prop));
		}
		#endregion
	}
}
